package com.sunlands.deskmate.message.config;

import com.sunlands.deskmate.message.handler.dispatcher.Dispatcher;
import com.sunlands.deskmate.message.handler.dispatcher.DispatcherManager;
import com.sunlands.deskmate.message.handler.receiver.MessageReceiverFactory;
import com.sunlands.deskmate.message.handler.receiver.Receiver;
import com.sunlands.deskmate.message.handler.storager.interceptor.Interceptor;
import com.sunlands.deskmate.message.handler.storager.interceptor.MessagePreInterceptorChain;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 消息处理配置类
 *
 * @author anjunling
 * @see com.sunlands.deskmate.message.handler.receiver.Receiver 消息接收器。接受不同类型消息
 * @see com.sunlands.deskmate.message.handler.mq.StorageMessageWorker 消息存储器。存储消息
 * @see com.sunlands.deskmate.message.handler.dispatcher.Dispatcher 消息分发器 私聊、群聊、室聊  以及离线消息处理
 * @see com.sunlands.deskmate.message.handler.sender.Sender 消息发送
 * <p>
 * 消息处理流程 WebSocketServerHandler -> Receiver -> mq -> StorageMessageWorker -> Dispatcher -> redis -> mq -> Sender
 */
@Configuration
public class MessageConfig {

    @Autowired
    private ApplicationContext applicationContext;

    /**
     * 返回所有的接收器管理器
     */
    @Bean
    public MessageReceiverFactory messageReceiverFactory() {
        Map<String, Receiver> receiverMap = applicationContext.getBeansOfType(Receiver.class);
        return new MessageReceiverFactory(receiverMap);
    }

    /**
     * 返回所有的分发器管理器
     */
    @Bean
    public DispatcherManager dispatcherManager() {
        Map<String, Dispatcher> dispatcherMap = applicationContext.getBeansOfType(Dispatcher.class);
        return new DispatcherManager(dispatcherMap);
    }

    /**
     * StorageMessageWorker中的拦截器，用于处理与消息发送处理无关的业务问题
     */
    @Bean
    public MessagePreInterceptorChain messagePreInterceptorChain() {
        List<Interceptor> beforeChain = new ArrayList<>(applicationContext.getBeansOfType(Interceptor.class).values());
        beforeChain = beforeChain.stream().sorted(Comparator.comparing(o -> o.getClass().getAnnotation(Order.class).value())).collect(Collectors.toList());
        return new MessagePreInterceptorChain(beforeChain);
    }

}
